require("dotenv").config();
var express = require("express");
var router = express.Router();
var jwt = require("jsonwebtoken");
// 加密
const crypto = require("node:crypto");
// 发送邮件
const nodemailer = require("nodemailer");
// 配置 SMTP 传输器
let transporter = nodemailer.createTransport({
  host: "smtp.qq.com",
  port: 465,
  secure: true,
  auth: {
    user: process.env.EMAIL_USER, // 从环境变量中读取邮箱地址
    pass: process.env.EMAIL_PASS, // 从环境变量中读取 SMTP 授权码
  },
});
const RECAPTCHA_SECRET_KEY = "6Ldgi-gpAAAAAJYdyyrVDhk2B1pIsFhmDzTjXV5t";
const axios = require("axios");
const UniSMS = require("unisms").default;

var { UserModel, PermissionsModel } = require("../model/user");

// 生成符合规范长度的密钥
function genkey(secret, length = 32) {
  return crypto
    .createHash("sha256")
    .update(String(secret))
    .digest("base64")
    .substr(0, length);
}

/* 重置密码申请 */
router.post("/resetPwd", async function (req, res, next) {
  // 随机验证码
  const { customAlphabet } = await import("nanoid");
  let { phone, email } = req.body;

  let list = { $or: [] };
  if (phone) {
    list.$or.push({ phone });
  }
  if (email) {
    list.$or.push({ email });
  }
  if (list.$or.length == 0) {
    list = {};
  }

  let obj = await UserModel.findOne(list);
  let msg = "手机号或邮箱不存在";
  let code = 201;
  let secret = "";

  if (obj) {
    // 随机6位验证码
    // 创建一个生成器，使用数字字符集
    const generateNumericCode = customAlphabet("123456789", 6);

    // 生成随机6位数字验证码
    const randomCode = generateNumericCode();
    // 邮件选项
    let mailOptions = {
      from: "1476435240@qq.com", // 发件人地址
      to: obj.email, // 收件人地址
      subject: "重置密码", // 邮件主题
      text: `验证码${randomCode},5分钟内有效。您正在重置密码,切勿向他人泄露`,
    };
    // 发送邮件
    transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        return console.log(error);
      }
      console.log("Email sent: " + info.response);
    });
    // 设置过期时间
    const expirationTime = Math.floor(Date.now() / 200) + 60 * 5; // 5分钟后过期
    await UserModel.updateOne(
      { phone: phone },
      { emailcode: randomCode, expirationtime: expirationTime }
    );
    // 加密字符串
    function encryptByAes256(content, secretkey, iv) {
      const cipher = crypto.createCipheriv(
        "aes-256-cbc",
        genkey(secretkey),
        genkey(iv, 16)
      );

      const dataWithExpiration = `${content}`;
      let enc = cipher.update(dataWithExpiration, "utf8", "hex");
      enc += cipher.final("hex");
      return enc;
    }
    // 加密后的字符串
    secret = encryptByAes256(req.body.phone, "a", "b");
    console.log(secret);

    msg = "查找成功";
    code = 200;
  }

  res.send({
    code,
    msg,
    secret,
  });
});

/* 修改密码，携带加密phone */
router.post("/updatePwd", async function (req, res, next) {
  // console.log(req.body)
  const { secret, password, emailcode } = req.body;

  let code = 201;
  let msg = "修改失败,已超时";

  // 解密字符串
  function decryptByAes256(content, secretkey, iv) {
    const decipher = crypto.createDecipheriv(
      "aes-256-cbc",
      genkey(secretkey),
      genkey(iv, 16)
    );
    let dec = decipher.update(content, "hex", "utf8");
    dec += decipher.final("utf8");

    const [plaintext, expirationTime] = dec.split("|");
    const currentTime = Math.floor(Date.now() / 200);

    if (currentTime > Number(expirationTime)) {
      return "";
    }

    return plaintext;
  }
  // 解密获得手机号
  const phone = decryptByAes256(secret, "a", "b");
  // 判断验证码
  let obj = await UserModel.findOne({ phone: phone });

  if (obj) {
    if (obj.emailcode != emailcode) {
      code = 201;
      msg = "验证码不正确";
    } else if (obj.expirationtime < Math.floor(Date.now() / 200)) {
      console.log(obj.expirationtime, Math.floor(Date.now() / 200));
      msg = "已超时";
    } else {
      await UserModel.updateOne(
        {
          phone,
        },
        {
          password,
        }
      );
      code = 200;
      msg = "修改成功";
    }
  }

  res.send({
    code,
    msg,
  });
});

// 登录
router.post("/login", async (req, res) => {
  let code = 203;
  let msg = "手机号不存在";
  let accessToken = "";
  let refreshToken = "";
  let { phone, password } = req.body;

  let user = await UserModel.findOne({ phone });

  if (user) {
    if (user.password != password) {
      (code = 201), (msg = "密码错误");
    } else {
      code = 200;
      msg = "登录成功";
      var MenuList = (
        await PermissionsModel.findOne({ _id: user.permissionsId })
      ).MenuList;
      accessToken =
        "Bearer " +
        jwt.sign({ ...user, num: Math.random() }, "123456", {
          expiresIn: "6h",
        });
      refreshToken =
        "Bearer " +
        jwt.sign({ ...user, num: Math.random() + 100 }, "123456", {
          expiresIn: "1d",
        });
    }
  }
  res.send({
    code,
    msg,
    // routeinfo,
    accessToken,
    refreshToken,
    MenuList: MenuList || [{}],
  });
});

//刷新短token
router.post("/refresh", async (req, res) => {
  // 获取用户信息
  const { phone } = req.body;

  let accessToken =
    "Bearer " + jwt.sign({ num: Math.random() }, "123456", { expiresIn: "6h" });
  let refreshToken =
    "Bearer " +
    jwt.sign({ num: Math.random() + 100 }, "123456", { expiresIn: "1d" });
  res.send({
    code: 200,
    accessToken,
    refreshToken,
  });
});

// 获取用户信息，token测试
router.get("/test", async (req, res) => {
  let user = await UserModel.find();
  res.send({
    code: 200,
    user,
    num: Math.random(),
  });
});

// 检查是否机器人操作
router.post("/verify-recaptcha", async (req, res) => {
  const { token } = req.body;
  const verificationUrl = `https://www.recaptcha.net/recaptcha/api/siteverify?secret=${RECAPTCHA_SECRET_KEY}&response=${token}`;

  try {
    const response = await axios.post(verificationUrl);
    const data = response.data;

    if (data.success) {
      res.send({
        code: 200,
        success: true,
        msg: "行为验证成功",
      });
    } else {
      res.send({
        code: 201,
        success: false,
        msg: "行为验证失败",
      });
    }
  } catch (error) {
    console.log(error);
  }
});

// 检查是否注册
router.post("/check-phone", async (req, res) => {
  const { phone } = req.body;
  let obj = await UserModel.findOne({ phone: phone });
  if (obj && (obj.password || obj.username)) {
    res.send({
      code: 201,
      success: false,
      msg: "该手机号已注册",
    });
  } else {
    res.send({
      code: 200,
      msg: "该手机号未注册",
    });
  }
});

// 发送短信
router.post("/send-sms", async (req, res) => {
  const { phone } = req.body;
  let obj = await UserModel.findOne({ phone: phone });

  if (obj) {
    if (!obj.password || !obj.username) {
      return res.send({
        code: 201,
        success: false,
        msg: "该手机号已注册",
      });
    }
  }

  const code = String(Math.floor(100000 + Math.random() * 900000));
  // const code = 111111
  // console.log(phone);
  await UserModel.create({ phone, smscode: String(code) });

  // 初始化
  const client = new UniSMS({
    accessKeyId: "PYjfFthpv1nAsaNHYT9jwPWDSo6uFDCZSRHee5XQuH15dxdTT",
  });

  // 发送短信
  client
    .send({
      to: phone,
      signature: "崔靖萱",
      templateId: "pub_verif_ttl2",
      templateData: {
        code,
        ttl: 5,
      },
    })
    .then((ret) => {
      // console.log(ret);
      res.send({
        code: 200,
        msg: "发送成功",
      });
    })
    .catch((e) => {
      console.error("send-sms-err", e);
      res.send({
        code: 201,
        msg: "发送失败",
      });
    });
});

// 检测用户名是否注册
router.post("/check-username", async (req, res) => {
  const { username } = req.body;
  let obj = await UserModel.findOne({ username });
  if (obj) {
    res.send({
      code: 201,
      msg: "用户名已被使用",
    });
  } else {
    res.send({
      code: 200,
      msg: "用户名未使用",
    });
  }
});

// 检查验证码
router.post("/check-sms-code", async (req, res) => {
  const { phone, smscode } = req.body;
  let obj = await UserModel.findOne({ phone: phone, smscode: smscode });
  if (!obj) {
    res.send({
      code: 201,
      msg: "验证码错误",
    });
  } else {
    res.send({
      code: 200,
      msg: "验证码正确",
    });
  }
});

// 获取角色列表
router.get("/get-role", async (req, res) => {
  let roleList = await PermissionsModel.find();
  res.send({
    code: 200,
    roleList,
  });
});

// 用户注册
router.post("/register", async (req, res) => {
  const { phone } = req.body;
  await UserModel.updateOne({ phone }, req.body);
  res.send({
    code: 200,
    msg: "注册成功",
  });
});

module.exports = router;
